package com.lu.manage.modular.system.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lu.manage.core.common.constant.SystemConstant;
import com.lu.manage.core.common.node.LayuiTreeNode;
import com.lu.manage.core.common.node.TreeNodes;
import com.lu.manage.core.tips.SuccessTip;
import com.lu.manage.core.utils.ToolUtil;
import com.lu.manage.modular.system.mapper.DeptMapper;
import com.lu.manage.modular.system.model.Dept;
import com.lu.manage.modular.system.service.DeptService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

/**
 * @program LuBoot
 * @description:
 * @author: zhanglu
 * @create: 2019-10-08 10:30:00
 */
@Service
public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements DeptService {

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Dept add(Dept dept) throws Exception {
        //组装属性，设置父级部门编号
        dept = this.deptSetPId(dept);
        this.save(dept);
        return dept;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void update(Dept newDept) throws Exception {
        //获取旧的部门
        String id = newDept.getId();
        Dept oldDept = this.getById(id);
        if(ToolUtil.isEmpty(oldDept)){
            throw new Exception("请求数据不完整或格式错误!");
        }

        //设置父级部门编号
        newDept = this.deptSetPId(newDept);

        //查找该节点的子集合,并修改相应的pcode和level(因为部门修改后,层级可能也变化了)
        updateSubDeptLevels(oldDept, newDept);

        this.updateById(newDept);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(String id) throws Exception {
        Dept dept = this.getById(id);

        //删除当前部门
        this.baseMapper.deleteById(id);

        //删除当前部门下的所有子部门
        List<Dept> depts = this.baseMapper.getDeptsLikePids(dept.getId());

        for (Dept d : depts) {
            this.baseMapper.deleteById(d.getId());
        }
    }

    @Override
    public Object listPage(Map<String, Object> map) {

        SuccessTip successTip = new SuccessTip();

        try {
            Page page = new Page(Integer.valueOf((String)map.get(SystemConstant.PAGE)), Integer.valueOf((String)map.get(SystemConstant.LIMIT)));

            IPage<Dept> deptIPage = this.baseMapper.listPage(page, map);

            successTip.setCount(deptIPage.getTotal());
            successTip.setData(deptIPage.getRecords());
        } catch (Exception e) {
            e.printStackTrace();
        }

        return successTip;
    }

    @Override
    public Object deptTreeList() {
        return this.baseMapper.deptTreeList();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void sortAllDepts(String nodes) throws Exception {
        List<TreeNodes> nodeList = JSONArray.parseArray(nodes, TreeNodes.class);
        for (TreeNodes node : nodeList) {
            handle(0, node);
        }
    }

    public void handle(int index, TreeNodes treeNodes){
        int count = 0;
        for (TreeNodes m : treeNodes.getChildren()) {
            count++;
            if(ToolUtil.isEmpty(m.getChildren())){
                Dept dept = new Dept();
                dept.setId(m.getId());
                dept.setSort(count);
                this.baseMapper.updateById(dept);
            }else {
                index++;
                handle(index, m);
                Dept dept = new Dept();
                dept.setId(m.getId());
                dept.setSort(index);
                this.baseMapper.updateById(dept);
            }
        }
    }

    @Override
    public Object deptLayuiTree() {

        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.orderByAsc("level", "sort");
        //查询所有部门
        List<Dept> deptList = this.baseMapper.selectList(queryWrapper);

        LayuiTreeNode layuiTreeNode = new LayuiTreeNode();

        //封装部门树
        return layuiTreeNode.nodeList(layuiTreeNode.convertDept(deptList), deptList.get(deptList.size() - 1).getLevel(), null);
    }

    @Override
    public Object deptLayuiTreeByPid(String deptId) {
        Dept dept = this.baseMapper.selectOne(Wrappers.<Dept>lambdaQuery().select(Dept::getPid).eq(Dept::getId, deptId));
        //删除当前部门下的所有子部门
        List<Dept> deptList = this.baseMapper.getDeptsLikePids(dept.getPid());

        LayuiTreeNode layuiTreeNode = new LayuiTreeNode();

        //封装部门树
        return layuiTreeNode.nodeList(layuiTreeNode.convertDept(deptList), deptList.get(deptList.size() - 1).getLevel(), null);
    }

    @Override
    public List<Dept> getDeptsLikePids(String id) {
        return this.baseMapper.getDeptsLikePids(id);
    }

    /**
     * 转化请求的数据：
     *  - 通过选择的父级id，设置自己的pcode、pcodes、levels
     * @param dept
     * @return
     */
    private Dept deptSetPId(Dept dept) {

        if(ToolUtil.isEmpty(dept.getPid()) || dept.getPid().equals("0")){
            dept.setPid(SystemConstant.pid);
            dept.setPids("[" + SystemConstant.pid + "],");
            dept.setLevel(SystemConstant.pLevels);
        }else {
            Dept pDept = this.getById(dept.getPid());
            dept.setPid(pDept.getId());
            dept.setLevel(pDept.getLevel() + 1);
            dept.setPids(pDept.getPids() + "[" + pDept.getId() + "],");
        }
        return dept;
    }

    /**
     * 更改所有子部门的结构
     * @param oldDept
     * @param newDept
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateSubDeptLevels(Dept oldDept, Dept newDept) {
        List<Dept> depts = this.baseMapper.getDeptsLikePids(oldDept.getId());

        for (Dept dept : depts) {
            //更新pid
            if(oldDept.getId().equals(dept.getPid() )){
                dept.setPid(newDept.getId());
            }

            //更新pids
            String oldPidsPrefix = oldDept.getPids() + "[" + oldDept.getId() + "],";
            String oldPidsSuffix = dept.getPids().substring(oldPidsPrefix.length());
            String deptPids = newDept.getPids() + "[" + newDept.getId() + "]," + oldPidsSuffix;
            dept.setPids(deptPids);

            //更新levels
            int level = StrUtil.count(deptPids, "[");
            dept.setLevel(level);

            this.updateById(dept);
        }
    }

}
